const prependSpace = function prependSpace(level) {
  let str = '';
  for (let i = 0; i < level; i++) {
    str += '    ';
  }
  return str;
};

const joinCode = function joinCode(list, level = 0) {
  const space = prependSpace(level); 
  return list.filter(x => x != null).map(x => space + x).join('\n');
};

const ps = {
  init(env) {
    env.level = 0;
  },
  Program(node, env) {
    let result = [];
    let item;
    for (item of node.body) {
      result.push(ps.process(item, env));
    }
    env.result = result;
    return joinCode(result);
  },
  VariableDeclaration(node, env) {
    return node.declarations.map((item) => {
      return ps.process(item, env);
    }).join('\n');
  },
  VariableDeclarator(node, env) {
    return `${ps.process(node.id, env)} = ${node.init ? ps.process(node.init, env) : 'None'}`;
  },
  Identifier(node, env) {
    return node.name;
  },
  Literal(node, env) {
    // 处理true和false
    switch (node.raw) {
      case 'true': {
        return 'True';
      }
      case 'false': {
        return 'False';
      }
      case 'undefined':
      case 'null': {
        return 'None';
      }
      default: {
        return node.raw;
      }
    }
  },
  WhileStatement(node, env) {
    const test = ps.process(node.test, env);
    const body = ps.process(node.body, env);
    return `while ${test}:\n${body}`;
  },
  IfStatement(node, env) {
    const test = ps.process(node.test, env);
    const consequent = ps.process(node.consequent, env);
    let str = `if ${test}:\n${consequent}`;
    const alternate = ps.process(node.alternate, env)
    if (node.alternate) str += `\nelse:\n${alternate}`;
    return str;
  },
  BinaryExpression(node, env) {
    return `${ps.process(node.left, env)} ${node.operator} ${ps.process(node.right, env)}`;
  },
  BlockStatement(node, env) {
    env.level++;
    const result = [];
    let item;
    for (item of node.body) {
      result.push(ps.process(item, env));
    }
    const str = joinCode(result, env.level);
    env.level--;
    return str;
  },
  ExpressionStatement(node, env) {
    return ps.process(node.expression, env);
  },
  AssignmentExpression(node, env) {
    return `${ps.process(node.left, env)} ${node.operator} ${ps.process(node.right, env)}`;
  },
  process(node, env) {
    const p = ps[node.type];
    if (!p) {
      console.error('未处理的类型', node.type, node);
      return;
    }
    const result = p(node, env);
    return result;
  },
};

export default ps;
